/*
 * graph2D
 * Copyright (c) 2009 Shun Moriya <shun@mnu.sakura.ne.jp>
 *
 * The MIT License
 * Permission is hereby granted, free of charge, to any person obtaining a copy
 * of this software and associated documentation files (the "Software"), to deal
 * in the Software without restriction, including without limitation the rights
 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
 * copies of the Software, and to permit persons to whom the Software is
 * furnished to do so, subject to the following conditions:
 *
 * The above copyright notice and this permission notice shall be included in
 * all copies or substantial portions of the Software.
 *
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
 * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,
 * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
 * OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR
 * THE USE OR OTHER DEALINGS IN THE SOFTWARE.
 */

#if !defined(___GRAPH2D_SCROLLBAR_H___)
#define ___GRAPH2D_SCROLLBAR_H___

#include "container.h"

namespace Graph2D
{
	/*!
	 * スクロールバー
	 */
	class ScrollBar : public Component
	{
		DISALLOW_COPY_AND_ASSIGN(ScrollBar);

		typedef Component super;

	public:
		enum Style
		{
			STYLE_HORIZON,		//<! 水平
			STYLE_VERTICAL		//<! 垂直
		};

	private:
		virtual ~ScrollBar()
		{
		}

	public:
		ScrollBar();

		virtual const char* getTypeName() const
		{
			return "ScrollBar";
		}

		/*! スクロールバースタイルの設定 */
		void setScrollBarStyle(const Style style)
		{
			this->style = style;
		}

		/*! 全体サイズの設定 */
		void setWholeSize(const float size)
		{
			wholeSize = size;
		}

		/*! 全体サイズの取得 */
		float getWholeSize() const
		{
			return wholeSize;
		}

		/*! ステップサイズの設定 */
		void SetStepSize(const float size)
		{
			stepSize = size;
		}

		/*! ステップサイズの取得 */
		float GetStepSize() const
		{
			return stepSize;
		}

		/*! ページサイズの設定 */
		void SetPageSize(const float size)
		{
			pageSize = size;
		}

		/*! ページサイズの取得 */
		float GetPageSize() const
		{
			return pageSize;
		}

		/*! ページ位置の設定 */
		void setPagePosition(const float position)
		{
			pagePosition = position;
		}

		/*! ページ位置の取得 */
		float getPagePosition() const
		{
			return pagePosition;
		}

		virtual bool onDraw(const DrawRect& drawRect);				//!< 描画
		virtual bool onTouchesBegan(const Vector2& localPosition);	//!< タッチ開始
		virtual bool onTouchesMoved(const Vector2& localPosition);	//!< タッチ移動
		virtual bool onTouchesEnded(const Vector2& localPosition);	//!< タッチ終了
		virtual bool onTouchesCancelled(const Vector2& localPosition);//!< タッチキャンセル

	private:
		void onTouchesEnd();

	protected:
		Style style;					//<! スクロールバースタイル
		float wholeSize;				//<! 全体サイズ
		float stepSize;					//<! ボタンを押した時の増加量
		float pageSize;					//<! ページサイズ
		float pagePosition;				//<! ページ位置
		float dragPoint;				//<! ドラッグを開始した位置
		bool scrollBarDrag;				//<! スクロールバーのドラッグ
		bool leftButtonPush;			//<! 左ボタンを押している
		bool rightButtonPush;			//<! 右ボタンを押している
	};
}

#endif

/*
 * graph2D
 * Copyright (c) 2009 Shun Moriya <shun@mnu.sakura.ne.jp>
 *
 * The MIT License
 * Permission is hereby granted, free of charge, to any person obtaining a copy
 * of this software and associated documentation files (the "Software"), to deal
 * in the Software without restriction, including without limitation the rights
 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
 * copies of the Software, and to permit persons to whom the Software is
 * furnished to do so, subject to the following conditions:
 *
 * The above copyright notice and this permission notice shall be included in
 * all copies or substantial portions of the Software.
 *
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
 * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,
 * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
 * OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR
 * THE USE OR OTHER DEALINGS IN THE SOFTWARE.
 */

#include "scrollBar.h"

namespace Graph2D
{
	//
	// スクロールバー
	//

	//! コンストラクタ
	ScrollBar::ScrollBar() : style(STYLE_HORIZON)
	{
		wholeSize = 1;
		stepSize = 1;
		pageSize = 1;
		pagePosition = 0;
		scrollBarDrag = false;
		leftButtonPush = false;
		rightButtonPush = false;
	}

	/*!
	 * 描画
	 */
	bool ScrollBar::onDraw(const DrawRect& drawRect)
	{
#if 0
		if(style == STYLE_HORIZON)
		{
			{
				const int offset = leftButtonPush ? 1 : 0;

				Frame::DrawFrame(
					leftButtonPush ? Frame::FS_PUSHED : Frame::FS_NORMAL,
					tDrawRect.drawX, tDrawRect.drawY, height, height,
					r, g, b, a
				);
				glColor4ub(r / 2, g / 2, b / 2, a);
				glBegin(GL_TRIANGLE_STRIP);
				glVertex2i(tDrawRect.drawX + height  /4 + offset, tDrawRect.drawY + height  /2 + offset);
				glVertex2i(tDrawRect.drawX + height*3/4 + offset, tDrawRect.drawY + height  /6 + offset);
				glVertex2i(tDrawRect.drawX + height*3/4 + offset, tDrawRect.drawY + height*5/6 + offset);
				glEnd();
			}
			{
				const int offset = rightButtonPush ? 1 : 0;

				Frame::DrawFrame(
					rightButtonPush ? Frame::FS_PUSHED : Frame::FS_NORMAL,
					tDrawRect.drawX + width - height, tDrawRect.drawY, height, height,
					r, g, b, a
				);
				glColor4ub(r / 2, g / 2, b / 2, a);
				glBegin(GL_TRIANGLE_STRIP);
				glVertex2i(tDrawRect.drawX + width-height  /4 + offset, tDrawRect.drawY + height  /2 + offset);
				glVertex2i(tDrawRect.drawX + width-height*3/4 + offset, tDrawRect.drawY + height  /6 + offset);
				glVertex2i(tDrawRect.drawX + width-height*3/4 + offset, tDrawRect.drawY + height*5/6 + offset);
				glEnd();
			}
			Frame::DrawFrame(
				Frame::FS_PUSHED|Frame::FS_NOLINE,
				tDrawRect.drawX + height, tDrawRect.drawY, width - height * 2, height,
				r*2/3, g*2/3, b*2/3, a
			);
			{
				const int maxwidth = width-height*2;
				int pos = maxwidth*pagePosition/wholeSize;
				int width = maxwidth*pageSize/wholeSize;
				if(width < 6)
					width = 6;
				if(pos+width > maxwidth)
					pos = maxwidth - width;
				if(pos<0)
					pos = 0;
				Frame::DrawFrame(
					Frame::FS_NORMAL,
					tDrawRect.drawX + height + pos, tDrawRect.drawY, width, height,
					r, g, b, a
				);
			}
		}
		else
		{
			{
				const int offset = leftButtonPush ? 1 : 0;

				Frame::DrawFrame(
					leftButtonPush ? Frame::FS_PUSHED : Frame::FS_NORMAL,
					tDrawRect.drawX, tDrawRect.drawY, width, width,
					r, g, b, a
				);
				glColor4ub(r / 2, g / 2, b / 2, a);
				glBegin(GL_TRIANGLE_STRIP);
				glVertex2i(tDrawRect.drawX + width     / 2 + offset, tDrawRect.drawY + width     / 4 + offset);
				glVertex2i(tDrawRect.drawX + width     / 6 + offset, tDrawRect.drawY + width * 3 / 4 + offset);
				glVertex2i(tDrawRect.drawX + width * 5 / 6 + offset, tDrawRect.drawY + width * 3 / 4 + offset);
				glEnd();
			}
			{
				const int offset = rightButtonPush ? 1 : 0;

				Frame::DrawFrame(
					rightButtonPush ? Frame::FS_PUSHED : Frame::FS_NORMAL,
					tDrawRect.drawX, tDrawRect.drawY + height - width, width, width,
					r, g, b, a
				);
				glColor4ub(r / 2, g / 2, b / 2, a);
				glBegin(GL_TRIANGLE_STRIP);
				glVertex2i(tDrawRect.drawX + width     / 2 + offset, tDrawRect.drawY + height - width     / 4 + offset);
				glVertex2i(tDrawRect.drawX + width     / 6 + offset, tDrawRect.drawY + height - width * 3 / 4 + offset);
				glVertex2i(tDrawRect.drawX + width * 5 / 6 + offset, tDrawRect.drawY + height - width * 3 / 4 + offset);
				glEnd();
			}
			Frame::DrawFrame(
				Frame::FS_PUSHED|Frame::FS_NOLINE,
				tDrawRect.drawX, tDrawRect.drawY + width, width, height - width * 2,
				r*2/3, g*2/3, b*2/3, a
			);
			{
				const int maxwidth = height - width * 2;
				int pos = maxwidth * pagePosition / wholeSize;
				int pag = maxwidth * pageSize / wholeSize;
				if(pag < 6)
					pag = 6;
				if(pos + pag > maxwidth)
					pos = maxwidth - width;
				if(pos < 0)
					pos = 0;
				Frame::DrawFrame(
					Frame::FS_NORMAL,
					tDrawRect.drawX, tDrawRect.drawY + width + pos, width, pag,
					r, g, b, a
				);
			}
		}
#endif
		return true;
	}

	bool ScrollBar::onTouchesBegan(const Vector2& localPosition)
	{
		float value, length, breadth;
		if(style == STYLE_HORIZON)
		{
			value = localPosition.x;
			length = getSize().x;
			breadth = getSize().y;
		}
		else
		{
			value = localPosition.y;
			length = getSize().y;
			breadth = getSize().x;
		}
		const float maxWidth = length - breadth * 2;

		float position = maxWidth * pagePosition / wholeSize;
		float width = maxWidth * pageSize / wholeSize;
		if(width < 6)
			width = 6;
		if(position + width > maxWidth)
			position = maxWidth - width;
		if(position < 0)
			position = 0;
		if(value < breadth)
		{
			leftButtonPush = true;
			pagePosition -= stepSize;
		}
		else if(value < breadth + position)
		{
			pagePosition -= pageSize;
		}
		else if(value < breadth + position + width)
		{
			scrollBarDrag = true;
			dragPoint = value - breadth - position;
		}
		else if(value < length - breadth)
		{
			pagePosition += pageSize;
		}
		else
		{
			rightButtonPush = true;
			pagePosition += stepSize;
		}
		if(pagePosition > wholeSize - pageSize)
		{
			pagePosition = wholeSize - pageSize;
		}
		if(pagePosition < 0)
		{
			pagePosition = 0;
		}

		setMouseCapture();

		return super::onTouchesBegan(localPosition);
	}

	bool ScrollBar::onTouchesMoved(const Vector2& localPosition)
	{
		if(getMouseCapture() != this)
			return super::touchesMoved(localPosition);

		if(scrollBarDrag)
		{
			float value, length, breadth;
			if(style == STYLE_HORIZON)
			{
				value = localPosition.x;
				length = getSize().x;
				breadth = getSize().y;
			}
			else
			{
				value = localPosition.y;
				length = getSize().y;
				breadth = getSize().x;
			}
			float maxWidth = length - breadth * 2;

			int position = static_cast<int>(value - dragPoint - breadth);
			if(maxWidth < 1)
				maxWidth = 1;
			pagePosition = position * wholeSize / maxWidth;
			if(pagePosition > wholeSize - pageSize)
				pagePosition = wholeSize - pageSize;
			if(pagePosition < 0)
				pagePosition = 0;
		}

		return true;
	}

	void ScrollBar::onTouchesEnd()
	{
		leftButtonPush = false;
		rightButtonPush = false;
		scrollBarDrag = false;
		releaseMouseCapture();
	}

	bool ScrollBar::onTouchesEnded(const Vector2& localPosition)
	{
		if(getMouseCapture() != this)
			return super::touchesEnded(localPosition);

		onTouchesEnd();

		return true;
	}

	bool ScrollBar::onTouchesCancelled(const Vector2& localPosition)
	{
		if(getMouseCapture() != this)
			return super::touchesEnded(localPosition);

		onTouchesEnd();

		return true;
	}
}
